﻿using MediatR;
using Medical.Api.Write.Application.Command.DepartmentManagement.Use;
using Medical.Domain.DepartmentInfo;
using Medical.ErrorCode;
using Medical.Interstructrue;
using Medical.Interstructrue.Base;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Medical.Api.Write.Application.Handler.DepartmentManagement.Use
{
    /// <summary>
    /// 使用表修改处理程序
    /// </summary>
    public class UpdateUseCommandHnadler : IRequestHandler<UpdateUseCommands, ApiResult<int>>
    {
        private readonly ILogger<UpdateUseCommandHnadler> logger;
        private readonly IBaseRepository<UseTable> useRep;
        private readonly IBaseRepository<ItemTable> itemRep;
        private readonly MedicalDbContext dbContext;

        /// <summary>
        /// 构造函数，注入所需依赖
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="useRep">使用表仓储</param>
        /// <param name="itemRep">物品表仓储</param>
        /// <param name="dbContext">数据库上下文</param>
        public UpdateUseCommandHnadler(
            ILogger<UpdateUseCommandHnadler> logger, 
            IBaseRepository<UseTable> useRep, 
            IBaseRepository<ItemTable> itemRep,
            MedicalDbContext dbContext)
        {
            this.logger = logger;
            this.useRep = useRep;
            this.itemRep = itemRep;
            this.dbContext = dbContext;
        }

        /// <summary>
        /// 处理使用表修改命令
        /// </summary>
        /// <param name="request">使用表修改命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>API结果</returns>
        public async Task<ApiResult<int>> Handle(UpdateUseCommands request, CancellationToken cancellationToken)
        {
            // 开启数据库事务
            using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                // 验证使用表数据
                if (request.useTable == null)
                {
                    logger.LogWarning("使用表数据为空");
                    return new ApiResult<int>()
                    {
                         Code = ApiEnums.Fail,
                         Data = 0,
                         Msg = "使用表数据不能为空"
                    };
                }
                
                // 检查要修改的使用表记录是否存在
                var existingUse = useRep.GetModel(request.useTable.Id);
                if (existingUse == null)
                {
                    logger.LogWarning("未找到ID为{Id}的使用表记录", request.useTable.Id);
                    return new ApiResult<int>()
                    {
                        Code = ApiEnums.NotFound,
                        Data = 0,
                        Msg = $"未找到ID为{request.useTable.Id}的使用表记录"
                    };
                }
                
                // 先分离实体，避免跟踪冲突
                dbContext.Entry(existingUse).State = EntityState.Detached;
                
                // 设置修改时间为当前时间
                request.useTable.UpdateTime = DateTime.Now;
                
                // 更新使用表
                useRep.Update(request.useTable);
                await dbContext.SaveChangesAsync(cancellationToken);
                
                // 获取原有的物品记录
                var existingItems = await dbContext.Set<ItemTable>()
                    .AsNoTracking()  // 使用AsNoTracking避免跟踪冲突
                    .Where(i => i.UseId == request.useTable.Id)
                    .ToListAsync(cancellationToken);
                
                // 如果有新的物品数据集合，则批量修改
                if (request.itemTables != null && request.itemTables.Any())
                {
                    // 需要删除的物品（不在新列表中的旧物品）
                    var itemsToDelete = existingItems.Where(existing => 
                        !request.itemTables.Any(newItem => newItem.Id == existing.Id && existing.Id != 0))
                        .ToList();
                        
                    if (itemsToDelete.Any())
                    {
                        // 使用ID删除物品，而不是直接删除实体对象
                        foreach (var itemToDelete in itemsToDelete)
                        {
                            var entity = await dbContext.Set<ItemTable>().FindAsync(itemToDelete.Id);
                            if (entity != null)
                            {
                                dbContext.Remove(entity);
                            }
                        }
                        logger.LogInformation("成功删除不再需要的物品表数据，数量：{0}", itemsToDelete.Count);
                    }
                    
                    foreach (var item in request.itemTables)
                    {
                        item.UseId = request.useTable.Id;
                        item.UpdateTime = DateTime.Now;
                        
                        // 新增物品
                        if (item.Id == 0)
                        {
                            item.IsDeleted = false;
                            item.CreateTime = DateTime.Now;
                            await dbContext.AddAsync(item, cancellationToken);
                        }
                        // 更新现有物品
                        else
                        {
                            // 先查找再更新，避免跟踪冲突
                            var existingItem = await dbContext.Set<ItemTable>().FindAsync(item.Id);
                            if (existingItem != null)
                            {
                                // 更新属性值
                                dbContext.Entry(existingItem).CurrentValues.SetValues(item);
                            }
                            else
                            {
                                // 如果找不到，可能是新增的
                                item.IsDeleted = false;
                                item.CreateTime = DateTime.Now;
                                await dbContext.AddAsync(item, cancellationToken);
                            }
                        }
                    }
                    
                    await dbContext.SaveChangesAsync(cancellationToken);
                    logger.LogInformation("成功批量修改物品表数据，数量：{0}", request.itemTables.Count);
                }
                
                // 提交事务
                await transaction.CommitAsync(cancellationToken);
                
                logger.LogInformation("成功修改使用表，ID：{0}", request.useTable.Id);
                return new ApiResult<int>()
                {
                    Code = ApiEnums.Success,
                    Data = request.useTable.Id,
                    Msg = "成功修改使用表"
                };
            }
            catch (Exception ex)
            {
                // 回滚事务
                await transaction.RollbackAsync(cancellationToken);
                
                logger.LogError(ex, "修改使用表时发生错误：{0}", ex.Message);
                return new ApiResult<int>()
                {
                    Code = ApiEnums.Fail,
                    Data = 0,
                    Msg = $"修改使用表失败：{ex.Message}"
                };
            }
        }
    }
}
